﻿using Abp.Domain.Repositories;
using Abp.Extensions;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace DHJ.Cost.Tasks
{
    public class BatchManager : CostDomainServiceBase, IBatchManager
    {
        private readonly IRepository<Batch, string> _batchRepository;

        private readonly IRepository<AssemRel> _assemRelRepository;

        public BatchManager(IRepository<Batch, string> batchRepository, IRepository<AssemRel> assemRelRepository)
        {
            _batchRepository = batchRepository;
            _assemRelRepository = assemRelRepository;
        }

        public virtual IQueryable<Batch> Batches() => _batchRepository.GetAll();

        public async Task<Batch> GetBatchById(string batchId)
        {
            if(batchId.IsNullOrWhiteSpace()) throw new ArgumentNullException();

            return await _batchRepository.GetAsync(batchId);
        }

        public async Task<List<AssemRel>> GetAssemRelsAsync(string batchId)
        {
            if (batchId.IsNullOrWhiteSpace()) throw new ArgumentNullException();

            var root = new AssemRel { PartId = batchId, PartQuantity = 1 };
            var result = new List<AssemRel> { root };

            IEnumerable<AssemRel> assemRels = result;
            while(true)
            {
                var partIds = assemRels.Select(a => a.PartId);
                assemRels = await _assemRelRepository.GetAll().Where(a => partIds.Contains(a.AssemId)).ToListAsync();
                if (!assemRels.Any()) break;
                result.AddRange(assemRels);
            }

            return result;
        }

        public async Task<List<FlatAssemRel>> GetFlatAssemRelsAsync(IBatchIdentifier batch)
        {
            if (batch.BatchId.IsNullOrWhiteSpace() || batch.Quantity <= 0) throw new ArgumentNullException();

            var root = new FlatAssemRel { PartId = batch.BatchId, PartQuantity = batch.Quantity };
            var result = new List<FlatAssemRel> { root };

            for (var i = 0; i < result.Count; i++)
            {
                var thisAssemRel = result[i];
                var assemRels = await _assemRelRepository.GetAll().Where(a => a.AssemId == thisAssemRel.PartId).ToListAsync();
                if (!assemRels.Any()) continue;
                var flatAssemRels = assemRels.Select(a => new FlatAssemRel(a, thisAssemRel.PartQuantity));
                result.AddRange(flatAssemRels);
            }

            return result;
        }
    }
}